
#include		"ConnectMenu.hh"

ConnectMenu::ConnectMenu(sf::RenderWindow &app, IGUI::e_context &f, sf::Event& e, Gomoku::Data &i)
  : info(i), focus(f), action(), App(app), Event(e), Input(this->App.GetInput()),
    st(0), wait(0), IP(sf::IPAddress::GetLocalAddress()), port(1024), focusText(0), w(0),
    goconnect(0), err(0)
{
  if (!this->bgm.LoadFromFile("sprites/bgmainmenu.jpg"))
    throw ImgException("LoadFromFile(sprites/bgmainmenu.jpg) in ConnectMenu.cpp");
  if (!this->cr.LoadFromFile("sprites/create.png"))
    throw ImgException("LoadFromFile(sprites/create.png) in ConnectMenu.cpp");
  if (!this->jo.LoadFromFile("sprites/join.png"))
    throw ImgException("LoadFromFile(sprites/join.png) in ConnectMenu.cpp");
  if (!this->input.LoadFromFile("sprites/input.png"))
    throw ImgException("LoadFromFile(sprites/input.png) in ConnectMenu.cpp");
  if (!this->jg.LoadFromFile("sprites/joingame.png"))
    throw ImgException("LoadFromFile(sprites/joingame.png) in ConnectMenu.cpp");
  this->action[sf::Event::KeyPressed] = &ConnectMenu::gere_key;
  this->action[sf::Event::MouseButtonPressed] = &ConnectMenu::mouse;
  this->action[sf::Event::MouseButtonReleased] = &ConnectMenu::mouser;
  this->action[sf::Event::Resized] = &ConnectMenu::resized;
  this->status.push_back(&ConnectMenu::create);
  this->status.push_back(&ConnectMenu::join);
  this->inputs.push_back(new GObject(this->input, 2));
  this->inputs.push_back(new GObject(this->input, 2));
  this->items.push_back(new GObject(this->cr, 3));
  this->items.push_back(new GObject(this->jo, 3));
  this->items.push_back(new GObject(this->jg, 3));
  this->items.push_back(new GObject(this->bgm));
  this->inputs[0]->setPos(450, 200);
  this->inputs[1]->setPos(450, 270);
  this->inputs[0]->resize(330, 45);
  this->inputs[1]->resize(330, 45);
  this->items[3]->resize(this->App.GetWidth(), this->App.GetHeight());
  this->items[0]->setPos(this->App.GetWidth() / 2 - this->items[0]->getW() / 2, 500);
  this->items[1]->setPos(this->App.GetWidth() / 2 - this->items[1]->getW() / 2, 500);
  this->items[2]->setPos(this->App.GetWidth() / 2 - this->items[2]->getW() / 2, 430);
  this->items[3]->setPos(-1, -1);
  this->str.SetFont(this->info.getGomofont());
  while (!Listener.Listen(this->port) && this->port < 7000)
    this->port++;
  if (this->port >= 7000)
    throw ImgException("No port avalaible in ConnectMenu.cpp");
  this->Listener.SetBlocking(false);
  this->inputs[0]->setState(1);
}

ConnectMenu::~ConnectMenu(void)
{
}

void		ConnectMenu::run(void)
{
  this->App.Clear();
  this->items[3]->draw(this->App);
  (this->*status[this->st])();
  this->mouseHover();
  if (this->action.find(this->Event.Type) != this->action.end())
    (this->*(this->action.find(this->Event.Type)->second))();
}

void		ConnectMenu::write(float x, float y, sf::Color color, std::string str)
{
  this->str.SetColor(color);
  this->str.SetPosition(x, y);
  this->str.SetText(str);
  this->App.Draw(this->str);
}

void		ConnectMenu::create(void)
{
  std::string	strp1;
  int		r3 = 0, r5 = 0;

  this->str.SetSize(this->info.getSizefont() + 5);
  this->write(260.f, 100.f, sf::Color(0, 0, 0), std::string("En attente d'un joueur ..."));
  this->str.SetSize(this->info.getSizefont());
  this->write(260.f, 200.f, sf::Color(0, 0, 0), std::string("IP: ") + IP.ToString());
  this->write(260.f, 270.f, sf::Color(0, 0, 0), std::string("Port: ") + TToString<int>(this->port));
  this->items[1]->draw(this->App);
  if (this->Listener.Accept(this->info.getNetwork().Client, &(this->info.getNetwork().ClientAddress)) != sf::Socket::NotReady)
    {
      this->info.getNetwork().isConnected = true;
      this->info.getNetwork().Client.SetBlocking(false); 
      this->info.getNetwork().Client.Receive(this->info.getNetwork().ServerPacket);
      while (!this->info.getNetwork().ServerPacket.EndOfPacket())
  	{
  	  this->info.getNetwork().ServerPacket >> strp1;
	  if (strp1 == "CONNECT CLIENT\n")
	    {
	      this->info.getNetwork().ServerPacket.Clear();
	      if (this->info.getRule3())
		r3 = 1;
	      if (this->info.getRule5break())
		r5 = 1;
	      this->info.getNetwork().ServerPacket << "RULES " + TToString<int>(r3) + " " + TToString<int>(r5) + " 50\n";
	      this->info.getNetwork().Client.Send(this->info.getNetwork().ServerPacket);
	      this->info.getNetwork().ServerPacket.Clear();
	      this->focus = IGUI::PVPB;
	    }
	  else
	    std::cout << strp1 << ": Command not found" << std::endl;
  	}
      this->info.getNetwork().ServerPacket.Clear();
    }
}

void		ConnectMenu::join(void)
{
  this->str.SetSize(this->info.getSizefont() - 5);
  this->write(250.f, 205.f, sf::Color(0, 0, 0), std::string("Adresse IP: "));
  this->write(250.f, 275.f, sf::Color(0, 0, 0), std::string("Port: "));
  this->inputs[0]->draw(this->App);
  this->inputs[1]->draw(this->App);
  this->refreshInputText();
  if (this->goconnect == 1)
    {
      this->goconnect = 0;
      this->err = 0;
      if (this->info.getNetwork().Client.Connect(atoi(this->info.getNetwork().connect_port.c_str()),
						 this->info.getNetwork().connect_ip.c_str()) != sf::Socket::Done)
	this->err = 1;
      if (this->err == 0)
	{
	  this->info.getNetwork().isConnected = true;
	  this->info.getNetwork().ClientPacket << "CONNECT CLIENT\n";
	  this->info.getNetwork().Client.Send(this->info.getNetwork().ClientPacket);
	  this->info.getNetwork().ClientPacket.Clear();
	  this->focus = IGUI::PVPW;
	}
    }
  if (this->err == 1)
    this->write(250.f, 345.f, sf::Color(255, 0, 0), std::string("Erreur de connection"));
  this->items[0]->draw(this->App);
  this->items[2]->draw(this->App);
}

void		ConnectMenu::refreshInputText(void)
{
  if (this->Event.Type == sf::Event::KeyReleased)
    this->w = 0;
  if (this->Event.Type == sf::Event::TextEntered)
    {
      if (((this->Event.Text.Unicode > 47 && this->Event.Text.Unicode < 58) || this->Event.Text.Unicode == '.') && this->w == 0)
	{
	  if (this->focusText == 0 && this->info.getNetwork().connect_ip.size() < 15)
	    this->info.getNetwork().connect_ip += static_cast<char>(this->Event.Text.Unicode);
	  else if (this->focusText == 1 && this->info.getNetwork().connect_port.size() < 4)
	    this->info.getNetwork().connect_port += static_cast<char>(this->Event.Text.Unicode);
	  this->w = 1;
	  this->err = 0;
	}
      else if (this->Event.Text.Unicode == 8 && this->w == 0)
	{
	  if (this->focusText == 0 && this->info.getNetwork().connect_ip.size() > 0)
	    this->info.getNetwork().connect_ip.erase(this->info.getNetwork().connect_ip.size() - 1, 1);
	  else if (this->focusText == 1 && this->info.getNetwork().connect_port.size() > 0)
	    this->info.getNetwork().connect_port.erase(this->info.getNetwork().connect_port.size() - 1, 1);
	  this->w = 1;
	  this->err = 0;
	}
    }
  this->str.SetSize(this->info.getSizefont() - 12);
  this->write(460.f, 205.f, sf::Color(0, 0, 0), this->info.getNetwork().connect_ip);
  this->write(460.f, 275.f, sf::Color(0, 0, 0), this->info.getNetwork().connect_port);
}

void		ConnectMenu::gere_key(void)
{
  switch (this->Event.Key.Code)
    {
    case sf::Key::Escape:
      this->focus = IGUI::MAINMENU;
      break;
    default:
      break;
    }
}

bool		ConnectMenu::checkHover(int i, std::vector<GObject*> &p)
{
  int		x = this->Input.GetMouseX();
  int		y = this->Input.GetMouseY();

  return (y >= p[i]->getY() &&
      y <= p[i]->getY() + p[i]->getH() &&
      x >= p[i]->getX() &&
      x <= p[i]->getX() + p[i]->getW());
}

void		ConnectMenu::mouse(void)
{
  int		i = (this->st + 1) % 2;

  if (this->checkHover(i, this->items))
    {
      this->items[i]->setState(2);
      this->wait = 1;
    }
  else
    this->items[i]->setState(0);
  if (this->checkHover(2, this->items))
    {
      this->items[2]->setState(2);
      this->wait = 1;
    }
  else
    this->items[2]->setState(0);
}

void		ConnectMenu::mouser(void)
{
  int		i = (this->st + 1) % 2;
  int		ft = (this->focusText + 1) % 2;

  if (this->checkHover(i, this->items) && this->wait == 1)
    {
      this->st = i;
      this->wait = 0;
    }
  if (this->checkHover(ft, this->inputs))
    {
      this->inputs[this->focusText]->setState(0);
      this->focusText = ft;
      this->inputs[ft]->setState(1);
    }
  if (this->checkHover(2, this->items) && this->wait == 1)
    {
      this->goconnect = 1;
      this->wait = 0;
    }
}

void		ConnectMenu::mouseHover(void)
{
  int		i = (this->st + 1) % 2;

  if (this->checkHover(i, this->items))
    this->items[i]->setState(1);
  else
    this->items[i]->setState(0);
  if (this->checkHover(2, this->items))
    this->items[2]->setState(1);
  else
    this->items[2]->setState(0);
}

void		ConnectMenu::resized(void)
{
  this->App.SetSize(1024, 768);
}
